package com.spzx.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.cart.api.RemoteCartService;
import com.spzx.cart.domain.CartInfo;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.rabbit.constant.MqConst;
import com.spzx.common.rabbit.service.RabbitService;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.order.domain.*;
import com.spzx.order.mapper.OrderInfoMapper;
import com.spzx.order.mapper.OrderItemMapper;
import com.spzx.order.mapper.OrderLogMapper;
import com.spzx.order.service.IOrderInfoService;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.domain.SkuLockVo;
import com.spzx.product.domain.SkuPrice;
import com.spzx.user.api.RemoteUserAddressService;
import com.spzx.user.domain.UserAddress;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements IOrderInfoService {

	@Autowired
	private RemoteCartService remoteCartService;
	@Autowired
	private RedisTemplate redisTemplate;
	@Autowired
	private OrderLogMapper orderLogMapper;
	@Autowired
	private RabbitService rabbitService;

	@Override
	public TradeVo createTrade() {
		Long userId = SecurityUtils.getUserId();
		List<CartInfo> tradeItems = remoteCartService.getCartCheckedList(SecurityConstants.INNER, userId).getData();
		TradeVo tradeVo = new TradeVo();

		List<OrderItem> orderItemList = tradeItems.stream().map(cartInfo -> {
			OrderItem orderItem = new OrderItem();
			BeanUtils.copyProperties(cartInfo, orderItem);
			return orderItem;
		}).toList();


		String tradeNo = getTradeNo(userId);
		tradeVo.setTradeNo(tradeNo);


		tradeVo.setOrderItemList(orderItemList);
		BigDecimal totalAmount = orderItemList.stream()
										 .map((orderItem ->
													   orderItem.getSkuPrice()
															   .multiply(new BigDecimal(orderItem.getSkuNum()))))
										 .reduce(BigDecimal.ZERO, BigDecimal::add);
		tradeVo.setTotalAmount(totalAmount);

		return tradeVo;
	}

	private String getTradeNo(Long userId) {
		// 订单流水号
		String tradeNo = UUID.randomUUID().toString().replaceAll("-", "");
		String key = "user:trade:" + userId;
		redisTemplate.opsForValue().set(key, tradeNo, 3, TimeUnit.MINUTES);
		return tradeNo;
	}

	// TODO 技术点: 提交订单
	@Autowired
	private RemoteProductService remoteProductService;

	@Override
	@Transactional
	public Long submitOrder(OrderForm orderForm) {
		// 验证重复提交 --> Redis
		// String tradeNo = orderForm.getTradeNo();
		// 查询Redis的流水号
		Long userId = SecurityUtils.getUserId();
		String key = "user:trade:" + userId;

		// 原版
		// String tradeNo_Redis = (String) redisTemplate.opsForValue().get(key);
		// // 比较
		// if (tradeNo_Redis == null || tradeNo_Redis.isEmpty() || !submitTradeNo.equals(tradeNo_Redis)) {
		// 	throw new ServiceException("订单重复提交");
		// }
		// // 删除交易流水号
		// redisTemplate.delete(key);
		// 新版 使用lua脚本保证获取key,比较和删除操作的原子性
		String scriptText = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
									"then\n" +
									"    return redis.call(\"del\",KEYS[1])\n" +
									"else\n" +
									"    return 0\n" +
									"end";
		DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
		redisScript.setScriptText(scriptText);
		redisScript.setResultType(Long.class);

		Long flag = (Long) redisTemplate.execute(redisScript,
				Arrays.asList(key),
				orderForm.getTradeNo());
		if (flag == 0) {
			throw new ServiceException("订单重复提交");
		}

		// 查询价格是否变化
		List<OrderItem> orderItemList = orderForm.getOrderItemList();
		List<Long> skuIds = orderItemList.stream().map(OrderItem::getSkuId).toList();
		// TODO 远程调用, 获取商品最新价格
		List<SkuPrice> skuPrices = remoteProductService.getSkuPriceList(skuIds, SecurityConstants.INNER).getData();
		Map<Long, BigDecimal> priceMap = skuPrices.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
		// 比较价格是否发生变化
		StringBuilder sb = new StringBuilder();
		for (OrderItem orderItem : orderItemList) {
			Long skuId = orderItem.getSkuId();
			BigDecimal salePrice = priceMap.get(skuId);
			if (salePrice.compareTo(orderItem.getSkuPrice()) != 0) {
				sb.append(orderItem.getSkuName()).append("价格发生变化了;");
			}
		}
		if (!sb.isEmpty()) {
			// 有商品价格变化
			throw new ServiceException(sb.toString());
		}
		//

		// 检验库存, 锁定库存 --> 分布式锁
		List<SkuLockVo> skuLockVoList = orderForm.getOrderItemList().stream().map(
				(item) -> {
					SkuLockVo skuLockVo = new SkuLockVo();
					skuLockVo.setSkuId(item.getSkuId());
					skuLockVo.setSkuNum(item.getSkuNum());
					return skuLockVo;
				}
		).toList();
		String message = remoteProductService.checkAndLock(orderForm.getTradeNo(), skuLockVoList, SecurityConstants.INNER).getData();
		if (message != null && !message.isEmpty()) {
			throw new ServiceException(message);
		}
		// 添加订单数据
		Long orderId = saveOrder(orderForm);
		// 删除购物车中商品
		remoteCartService.deleteCartCheckList(SecurityConstants.INNER, userId);
		// TODO 订单信息30min未支付, 自动取消订单
		rabbitService.sendDealyMessage(MqConst.EXCHANGE_CANCEL_ORDER,
				MqConst.ROUTING_CANCEL_ORDER,
				String.valueOf(orderId),
				MqConst.CANCEL_ORDER_DELAY_TIME);

		return orderId;
	}

	@Override
	public void processCancelOrder(String orderId) {

		// 查询订单状态
		OrderInfo orderInfo = getById(orderId);
		if (orderInfo == null || orderInfo.getOrderStatus().intValue() != 0) {
			// 订单不存在
			return;
		}
		// 取消订单
		orderInfo.setOrderStatus(-1);
		orderInfo.setCancelTime(new Date());
		orderInfo.setCancelReason("订单超时未支付, 自动取消订单");
		updateById(orderInfo);
		// 记录日志
		OrderLog orderLog = new OrderLog();
		orderLog.setOrderId(orderInfo.getId());
		orderLog.setProcessStatus(-1L);
		orderLog.setOperateUser("系统");
		orderLog.setNote("订单超时未支付, 自动取消订单");
		orderLogMapper.insert(orderLog);
		// 解锁库存 MQ异步解锁
		rabbitService.sendMessage(MqConst.EXCHANGE_PRODUCT, MqConst.QUEUE_UNLOCK, orderInfo.getOrderNo());
	}

	@Override
	public OrderInfo getOrderInfo(Long orderId) {
		OrderInfo byId = getById(orderId);
		return byId;
	}

	@Override
	public List<OrderItem> userOrderInfoList(Integer pageNum, Integer pageSize, Integer orderStatus) {
		Long userId = SecurityUtils.getUserId();
		Page<OrderInfo> page = new Page<>(pageNum, pageSize);
		LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>(OrderInfo.class)
																			.eq(OrderInfo::getUserId, userId)
																			.eq(orderStatus != null, OrderInfo::getOrderStatus, orderStatus)
																			.orderByDesc(OrderInfo::getCreateTime);
		List<OrderInfo> orderList = list(queryWrapper);
		List<Long> orderIds = orderList.stream().map(OrderInfo::getId).toList();
		List<OrderItem> orderItemList = orderItemMapper.selectList(new LambdaQueryWrapper<>(OrderItem.class)
																			.in(OrderItem::getOrderId, orderIds));

		return orderItemList;
	}

	@Autowired
	private RemoteUserAddressService remoteUserAddressService;
	@Autowired
	private OrderInfoMapper orderInfoMapper;
	@Autowired
	private OrderItemMapper orderItemMapper;

	public Long saveOrder(OrderForm orderForm) {
		// 获取当前登录用户的id
		Long userId = SecurityContextHolder.getUserId();
		String userName = SecurityContextHolder.getUserName();

		OrderInfo orderInfo = new OrderInfo();
		orderInfo.setOrderNo(orderForm.getTradeNo());
		orderInfo.setUserId(userId);
		orderInfo.setNickName(userName);
		orderInfo.setRemark(orderForm.getRemark());
		UserAddress userAddress = remoteUserAddressService.getUserAddress(orderForm.getUserAddressId(), userId, SecurityConstants.INNER).getData();
		orderInfo.setReceiverName(userAddress.getName());
		orderInfo.setReceiverPhone(userAddress.getPhone());
		orderInfo.setReceiverTagName(userAddress.getTagName());
		orderInfo.setReceiverProvince(userAddress.getProvinceCode());
		orderInfo.setReceiverCity(userAddress.getCityCode());
		orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
		orderInfo.setReceiverAddress(userAddress.getFullAddress());

		List<OrderItem> orderItemList = orderForm.getOrderItemList();
		BigDecimal totalAmount = new BigDecimal(0);
		for (OrderItem orderItem : orderItemList) {
			totalAmount = totalAmount.add(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())));
		}
		orderInfo.setTotalAmount(totalAmount);
		orderInfo.setCouponAmount(new BigDecimal(0));
		orderInfo.setOriginalTotalAmount(totalAmount);
		orderInfo.setFeightFee(orderForm.getFeightFee());
		// OrderInfo类的orderStatus属性的类型改为Integer
		orderInfo.setOrderStatus(0);
		orderInfoMapper.insert(orderInfo);

		// 保存订单明细
		for (OrderItem orderItem : orderItemList) {
			orderItem.setOrderId(orderInfo.getId());
			orderItemMapper.insert(orderItem);
		}

		// 记录日志
		OrderLog orderLog = new OrderLog();
		orderLog.setOrderId(orderInfo.getId());
		orderLog.setProcessStatus(0L);
		orderLog.setNote("提交订单");
		orderLogMapper.insert(orderLog);
		return orderInfo.getId();
	}


}